package com.swt.gap.controller;

import com.swt.gap.common.graph.GraphNeo4jVO;
import com.swt.gap.model.params.SearchNodeByProperty;
import com.swt.gap.model.vo.graph.NetworkAnalyseVO;
import com.swt.gap.model.vo.graph.PathAnalyzeVO;
import com.swt.gap.model.vo.graph.SaveResultFileVO;
import com.swt.gap.service.GraphService;
import io.swagger.annotations.*;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Set;

/**
 * 请填写说明
 *
 * @author sx
 * @date 2020/5/13 9:29
 */
@Api(tags = "图谱分析")
@RestController
@RequestMapping("/graph")
public class GraphController {

    private final GraphService graphService;

    public GraphController(GraphService graphService) {
        this.graphService = graphService;
    }



    @ApiOperation(value = "搜索节点")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "int", name = "taskId", required = true),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "keyword", required = true)
    })
    @ApiResponse(code = 200, message = "ok", response = GraphNeo4jVO.Node.class, responseContainer = "List")
    @GetMapping("/node")
    public ResponseEntity<List<GraphNeo4jVO.Node>> listNodeByName(@RequestParam String keyword, @RequestParam Integer taskId) {

        return ResponseEntity.ok(graphService.listNodeByName(keyword, taskId));
    }

    @ApiOperation(value = "路径分析")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", dataType = "PathAnalyzeVO", name = "pathAnalyzeVO", required = true),
    })
    @ApiResponse(code = 200, message = "ok", response = GraphNeo4jVO.class)
    @PostMapping("/path")
    public ResponseEntity getPath(@RequestBody PathAnalyzeVO pathAnalyzeVO) {
        return ResponseEntity.ok(graphService.getPath(pathAnalyzeVO));
    }


    @ApiOperation(value = "活跃度分析")
    @ApiImplicitParam(paramType = "query", dataType = "int", name = "taskId", value = "任务id 必填", required = true)
    @ApiResponses(
            {@ApiResponse(code = 200, message = "ok", response = NetworkAnalyseVO.class, responseContainer = "List")})
    @GetMapping("/activity")
    public ResponseEntity activityAnalyse(@RequestParam Integer taskId){
        return ResponseEntity.ok(graphService.activityAnalyse(taskId));
    }

    @ApiOperation(value = "重要度分析")
    @ApiImplicitParam(paramType = "query", dataType = "int", name = "taskId", value = "任务id 必填", required = true)
    @ApiResponses(
            {@ApiResponse(code = 200, message = "ok", response = NetworkAnalyseVO.class, responseContainer = "List")})
    @GetMapping("/importance")
    public ResponseEntity importanceAnalyse(@RequestParam Integer taskId){
        return ResponseEntity.ok(graphService.importanceAnalyse(taskId));
    }

    @ApiOperation(value = "中心地位分析")
    @ApiImplicitParam(paramType = "query", dataType = "int", name = "taskId", value = "任务id 必填", required = true)
    @ApiResponses(
            {@ApiResponse(code = 200, message = "ok", response = NetworkAnalyseVO.class, responseContainer = "List")})
    @GetMapping("/betweenness")
    public ResponseEntity<List<NetworkAnalyseVO>> betweennessAnalyse(@RequestParam Integer taskId){
        return ResponseEntity.ok(graphService.betweennessAnalyse(taskId));
    }


    @ApiOperation(value = "结点扩展")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "array", name = "nodeIds",  value = "节点id"),
            @ApiImplicitParam(paramType = "query", dataType = "int", name = "taskId", value = "任务id"),
            @ApiImplicitParam(paramType = "query", dataType = "int", name = "menuTypeCode", value = "菜单类型，1实体2事件3文档4外部"),
            @ApiImplicitParam(paramType = "query", dataType = "int", name = "pageNum"),
            @ApiImplicitParam(paramType = "query", dataType = "int", name = "pageSize")
    })
    @ApiResponse(code = 200, message = "ok", response = GraphNeo4jVO.class)
    @GetMapping("/expend-graph")
    public ResponseEntity<GraphNeo4jVO> expendByNodes(@RequestParam("nodeIds") String[] nodeIds,
                                        @RequestParam(value = "taskId")Integer taskId,
                                        @RequestParam(value = "menuTypeCode")Integer menuTypeCode,
                                        @RequestParam(value = "pageNum", required = false) Integer pageNum,
                                        @RequestParam(value = "pageSize", required = false) Integer pageSize) {
        return ResponseEntity.ok(graphService.expendByNodes(nodeIds, taskId, menuTypeCode, pageNum, pageSize));
    }


    @ApiOperation(value = "事件拆分")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "startNodeId", required = true),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "endNodeId", required = true),
            @ApiImplicitParam(paramType = "query", dataType = "int", name = "taskId", value = "任务id，非必填", required = true)
    })
    @ApiResponse(code = 200, message = "ok", response = GraphNeo4jVO.class)
    @GetMapping("/event/un-merge")
    public ResponseEntity<GraphNeo4jVO> unmergeEvent(@RequestParam("startNodeId") String startNodeId,
                                       @RequestParam("endNodeId") String endNodeId,
                                       @RequestParam(value = "taskId")Integer taskId) {
        return ResponseEntity.ok(graphService.unmergeEvent(startNodeId, endNodeId, taskId));
    }


    @ApiOperation(value = "结点入向连接top10")
    @ApiImplicitParam(paramType = "query", dataType = "int", name = "taskId", value = "任务id 必填", required = true)
    @ApiResponses(
            {@ApiResponse(code = 200, message = "ok", response = NetworkAnalyseVO.class, responseContainer = "List")})
    @GetMapping("/in-degree")
    public ResponseEntity<List<NetworkAnalyseVO>> indegreeCount(@RequestParam Integer taskId){
        return ResponseEntity.ok(graphService.indegreeCount(taskId));
    }

    @ApiOperation(value = "结点出向连接top10")
    @ApiImplicitParam(paramType = "query", dataType = "int", name = "taskId", value = "任务id 必填", required = true)
    @ApiResponses(
            {@ApiResponse(code = 200, message = "ok", response = NetworkAnalyseVO.class, responseContainer = "List")})
    @GetMapping("/out-degree")
    public ResponseEntity<List<NetworkAnalyseVO>> outdegreeCount(@RequestParam Integer taskId){
        return ResponseEntity.ok(graphService.outdegreeCount(taskId));
    }

    @ApiOperation(value = "保存结果到本地文件", notes = "保存结果到本地文件")
    @PostMapping("/graph-file")
    public ResponseEntity exportGraphFile(@RequestBody SaveResultFileVO saveResultFile) throws IOException {
        String content = saveResultFile.getContent();
        //解决文件名乱码问题
        String fileName = saveResultFile.getFileName() + ".swtg";
        fileName = URLEncoder.encode(fileName, "utf-8").replaceAll("\\+", "%20");
        HttpHeaders headers = new HttpHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", fileName));
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");
        InputStream inputStream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
        return ResponseEntity
                .ok()
                .headers(headers)
                .contentLength(inputStream.available())
                .contentType(MediaType.parseMediaType("application/octet-stream"))
                .body(new InputStreamResource(inputStream));

    }


    @ApiOperation(value = "导入子图，上传swtg文件", notes = "上传swtg文件")
    @PostMapping("/upload")
    public ResponseEntity<String> parseXML(@RequestParam("file") MultipartFile file) throws IOException {
        String originalFileName = file.getOriginalFilename();
        assert originalFileName != null;
        if (originalFileName.endsWith(".swtg")) {
            Reader reader = new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8);
            int ch = 0;
            StringBuilder sb = new StringBuilder();
            while ((ch = reader.read()) != -1) {
                sb.append((char) ch);
            }
            reader.close();
            String content = sb.toString();
            return ResponseEntity.ok(content);
        }
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("文件格式不正确");
    }

    @ApiOperation(value = "获取任务下所有节点类型")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "int", name = "taskId", required = true)
    })
    @ApiResponse(code = 200, message = "ok", response = String.class, responseContainer = "List")
    @GetMapping("/labels")
    public ResponseEntity<Set<String>> listNodeByName(@RequestParam Integer taskId) {

        return ResponseEntity.ok(graphService.listLabelsByTaskId( taskId));
    }

    @ApiOperation(value = "根据节点类型获取属性key")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "int", name = "taskId", required = true),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "label", required = true)
    })
    @ApiResponse(code = 200, message = "ok", response = String.class, responseContainer = "List")
    @GetMapping("/property-key")
    public ResponseEntity<Set<String>> listKeysByLabel(@RequestParam Integer taskId, @RequestParam String label) {

        return ResponseEntity.ok(graphService.listKeysByLabel(taskId, label));
    }

    @ApiOperation(value = "根据属性搜索节点")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", dataType = "SearchNodeByProperty", name = "property", required = true)
    })
    @ApiResponse(code = 200, message = "ok", response = GraphNeo4jVO.Node.class, responseContainer = "List")
    @PostMapping("/property-entity")
    public ResponseEntity<List<GraphNeo4jVO.Node>> listNodeByProperty(@RequestBody SearchNodeByProperty property) {
        return ResponseEntity.ok(graphService.listNodeByProperty(property));
    }

    @ApiOperation(value = "根据节点id获取边")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "int", name = "taskId", required = true),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "nodeId", required = true)
    })
    @ApiResponse(code = 200, message = "ok", response = GraphNeo4jVO.Link.class, responseContainer = "List")
    @GetMapping("/link")
    public ResponseEntity<List<GraphNeo4jVO.Link>> listLinkByNodeId(@RequestParam String nodeId, @RequestParam Integer taskId) {

        return ResponseEntity.ok(graphService.listLinkByNodeId(nodeId, taskId));
    }


}
